from CvPythonExtensions import *

import GerikSpells
from GerikSpells import GerikSpellBase
from GSGroupPolicies import GSAll as GSGroup
from GSHandlerPolicies import GSTargetting as GSHandler

from GSTargetInfoPolicies import GSSinglePlotTarget
from GSGraphicsPolicies import GSPlot

from GSResultsPolicies import GSMission as GSResults

import GerikSpellsUtils

gc = CyGlobalContext()

class Patrol(GerikSpellBase, GSGroup, GSHandler, GSResults):
    def __init__(self):
        GerikSpellBase.__init__(self)
        GSGroup.__init__(self)
        
        # This spell uses two stages, both being simple plot targetting.
        stageList = []

        pPlotTargetPolicy = GSSinglePlotTarget(self.canTargetPlot)
        pPlotGraphicsPolicy = GSPlot()
        pPlotGraphicsPolicy.setCursorType("CURSOR_PATROL")
        stageList.append( (pPlotTargetPolicy, pPlotGraphicsPolicy) )

        pPlotTargetPolicy = GSSinglePlotTarget(self.canTargetPlot)
        pPlotGraphicsPolicy = GSPlot()
        pPlotGraphicsPolicy.setCursorType("CURSOR_PATROL_BACK")
        stageList.append( (pPlotTargetPolicy, pPlotGraphicsPolicy) )


        GSHandler.__init__(self, stageList)
        GSResults.__init__(self, pPlotTargetPolicy)

    def canUnitCast(self, pCastingUnit, pPlot, bVisible):
        if (pCastingUnit.getUnitType() == gc.getInfoTypeForString("UNIT_WARRIOR")):
            return True

    def canTargetPlot(self, pCastingGroup, pCastingPlot, pPotentialTarget, bVisible):
        return True

    def castSpell(self, pTargetInfo):
        # First, push the mission to move the unit to the first point.
        pPlot1 = self.getTargettingResults(0)
        gc.getGame().selectionListGameNetMessage(GameMessageTypes.GAMEMESSAGE_PUSH_MISSION, MissionTypes.MISSION_MOVE_TO, pPlot1.getData1(), pPlot1.getData2(), -1, False, False)

        # Next, push the spell mission, with data as the far plot.
        # When the unit gets to the first plot, it will start the spell mission. "shift" is true to ensure that the mission is appended.
        
        # Check for if the unit just patrols one square. Avoid infinite looping if so.
        if pPlot1.getData1() == pTargetInfo.getData1():
            if pPlot1.getData2() == pTargetInfo.getData2():
                return
        self.pushSpellMissionAltShift(pTargetInfo.getData1(), pTargetInfo.getData2(), pTargetInfo.getData3(), False, True)
        

    # When the spell mission starts, it's instantly replaced by two moves.
    # 1.) The first move to the far plot, known by the data.
    # 2.) The second move will be back to the near pot, known because that's where the unit started.
    # 3.) Finally, push another of these spell missions onto the end in order to repeat the cycle.
    #
    # Remember, this is run on all computer, so the pushMissions and pushSpellMisionAltShift calls are MP-safe.
    def startSpellResultsOnTarget(self, pCastingGroup, pTarget):
        pCastingGroup.pushMission(MissionTypes.MISSION_MOVE_TO, pTarget.getX(), pTarget.getY(), 0, True, False,
                         MissionAITypes.NO_MISSIONAI, pTarget, pCastingGroup.getHeadUnit())
        pCastingGroup.pushMission(MissionTypes.MISSION_MOVE_TO, pCastingGroup.plot().getX(), pCastingGroup.plot().getY(), 0, True, False,
                         MissionAITypes.NO_MISSIONAI, pTarget, pCastingGroup.getHeadUnit())
        pCastingGroup.pushSpellMission(self.getSpellNumber(), pTarget.getX(), pTarget.getY(), -1, True)
        return False
